package controller

import (
	"encoding/json"
	"fmt"
	"gin/common"
	"gin/model"
	"gin/response"
	"gin/util"
	"github.com/gin-gonic/gin"
	"github.com/go-redis/redis"
	"github.com/jinzhu/gorm"
	"strconv"
	"time"
)

func Calculate(ctx *gin.Context) {
	goodsJsonStr := ctx.PostForm("goodsJsonStr")
	shopId := ctx.PostForm("shopId")
	if len(shopId) == 0 {
		response.Fail(ctx, gin.H{}, "缺少店铺标识")
		return
	}
	var goods []model.GoodsJson
	if err := json.Unmarshal([]byte(goodsJsonStr), &goods); err != nil {
		fmt.Println("Unmarshal goods", err.Error())
		return
	}
	Db := common.GetDB()
	user, _ := ctx.Get("user")
	var allPrice float64
	var goodsNumber int
	var goodsOrder []model.OrderGoods
	var gogo model.OrderGoods
	for _, value := range goods {
		var goodsInfo model.GoodsInfo
		Db.Debug().Table("cat_meal_goods").Where("id=?", value.GoodsId).First(&goodsInfo)
		if len(value.PropertyChildIds) > 0 {
			var sku model.SkuPrice
			Db.Debug().Table("cat_meal_goods_sku").Where("goodsId=? and propertyChildIds=?", value.GoodsId, util.Substr(value.PropertyChildIds, 0, 0)+",").First(&sku)
			fmt.Println(sku)

			price := sku.Price * float64(value.Number)
			allPrice += price
			gogo.Property = sku.PropertyChildNames
			gogo.Amount = sku.Price
			gogo.Property = sku.PropertyChildNames
			gogo.Amount = sku.Price
		} else {
			gogo.Property = "无"
			gogo.Amount = goodsInfo.MinPrice
		}
		gogo.Number = value.Number
		gogo.Pic = goodsInfo.Pic
		gogo.GoodsName = goodsInfo.Name
		goodsOrder = append(goodsOrder, gogo)
		goodsNumber += value.Number
	}
	//配送费
	var AmountLogistics float64
	var shopInfo Shop
	Db.Debug().Table("cat_meal_shop").Where("id=? ", shopId).First(&shopInfo)
	var resDist float64
	//配送
	sendType := ctx.PostForm("sendType")
	if sendType == "kd" { //快递
		if allPrice < shopInfo.SendMoney {
			response.Fail(ctx, gin.H{}, "满"+strconv.FormatFloat(shopInfo.SendMoney, 'f', 2, 64)+"元起能配送")
			return
		}
		addressId := ctx.PostForm("addressId")
		if len(addressId) == 0 {
			response.Fail(ctx, gin.H{}, "缺少地址标识")
			return
		}
		var adInfo model.AddressInfo
		Db.Debug().Table("cat_meal_address").Where("id=? and uid =?", addressId, user.(model.UserInfo).Uid).First(&adInfo)
		if adInfo.Id == 0 {
			response.Fail(ctx, gin.H{}, "地址有误")
			return
		}
		//计算收货地址与店铺地址的距离
		newLat, _ := strconv.ParseFloat(adInfo.Latitude, 64) //64位转字符串
		newlng, _ := strconv.ParseFloat(adInfo.Longitude, 64)
		redisDB := common.GetRedis()
		_, err := redisDB.GeoAdd("shopList", &redis.GeoLocation{
			Name:      "address_id_" + strconv.Itoa(adInfo.Id),
			Longitude: newlng,
			Latitude:  newLat,
		}).Result()
		if err != nil {
			return
		}
		resDist, _ := redisDB.GeoDist("shopList", "address_id_"+strconv.Itoa(adInfo.Id), "shop_"+shopId, "m").Result()
		if resDist > shopInfo.SendDistance {
			response.Fail(ctx, gin.H{}, "超出配送范围，只支持"+strconv.FormatFloat(resDist, 'f', 2, 64)+"m")
			return
		}

		//通过距离计算配送费
		var logis map[string]int
		err = json.Unmarshal([]byte(shopInfo.AmountLogistics), &logis)
		if err != nil {
			return
		}
		for key, lValue := range logis {
			fmt.Printf("%T--%T--%T", key, lValue, resDist)
			area, _ := strconv.ParseFloat(key, 64)
			lValue2, _ := strconv.ParseFloat(strconv.Itoa(lValue), 64)
			if resDist > area {
				AmountLogistics = lValue2
			}
		}
	}
	//优惠券
	couponId := ctx.PostForm("couponId")
	var CouponMoney float64
	if len(couponId) != 0 {
		var MyCou model.MyCouponsInfo
		Db.Debug().Table("cat_meal_address").Where("status=0 and id=? and uid =? and shopId", couponId, user.(model.UserInfo).Uid, shopId).First(&MyCou)
		if allPrice >= MyCou.MoneyHreshold {
			CouponMoney = MyCou.Money
		}
	}
	//会员等级
	var AmountLevel float64
	if user.(model.UserInfo).Level > 0 {
		var myLevel model.LevelInfo
		Db.Debug().Table("cat_meal_level").Where(" id=?", user.(model.UserInfo).Level).First(&myLevel)

		AmountLevel, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", myLevel.Rebate*allPrice/100), 64)
	}

	var MyCouList []model.MyCouponsInfo
	Db.Debug().Table("cat_meal_user_coupons").Where("status=0 and uid =? and moneyHreshold<? ", user.(model.UserInfo).Uid, allPrice).Order("id desc").Find(&MyCouList)
	response.Success(ctx, gin.H{
		"distance":        resDist,
		"AmountLevel":     AmountLevel,
		"goodsNumber":     goodsNumber,
		"couponUserList":  MyCouList,
		"amountTotal":     allPrice,
		"amountReal":      allPrice + AmountLogistics - CouponMoney - AmountLevel,
		"AmountLogistics": AmountLogistics, "CouponMoney": CouponMoney}, "SUCCESS")
}

func OrderAdd(ctx *gin.Context) {
	goodsJsonStr := ctx.PostForm("goodsJsonStr")
	shopId := ctx.PostForm("shopId")
	if len(shopId) == 0 {
		response.Fail(ctx, gin.H{}, "缺少店铺标识")
		return
	}
	var goods []model.GoodsJson
	if err := json.Unmarshal([]byte(goodsJsonStr), &goods); err != nil {
		fmt.Println("Unmarshal goods", err.Error())
		return
	}
	Db := common.GetDB()
	user, _ := ctx.Get("user")
	var allPrice float64
	var goodsNumber int
	var goodsOrder []model.OrderGoods
	var gogo model.OrderGoods
	for _, value := range goods {
		var goodsInfo model.GoodsInfo
		Db.Debug().Table("cat_meal_goods").Where("id=?", value.GoodsId).First(&goodsInfo)
		if len(value.PropertyChildIds) > 0 {
			var sku model.SkuPrice
			go Db.Debug().Table("cat_meal_goods_sku").Where("goodsId=? and propertyChildIds=?", value.GoodsId, util.Substr(value.PropertyChildIds, 1, 0)+",").First(&sku)
			price := sku.Price * float64(value.Number)
			allPrice += price
			gogo.Property = sku.PropertyChildNames
			gogo.Amount = sku.Price
			gogo.Property = sku.PropertyChildNames
			gogo.Amount = sku.Price
		} else {
			gogo.Property = "无"
			gogo.Amount = goodsInfo.MinPrice
		}
		gogo.Number = value.Number
		gogo.Pic = goodsInfo.Pic
		gogo.GoodsName = goodsInfo.Name
		goodsOrder = append(goodsOrder, gogo)
		goodsNumber += value.Number
	}
	//配送费
	var AmountLogistics float64
	var shopInfo Shop
	Db.Debug().Table("cat_meal_shop").Where("id=? ", shopId).First(&shopInfo)
	if shopInfo.ShopId == 0 {
		response.Fail(ctx, gin.H{}, "缺少店铺标识")
		return
	}
	var adInfo model.AddressInfo
	//配送
	sendType := ctx.PostForm("sendType")
	if sendType == "kd" { //快递
		if allPrice < shopInfo.SendMoney {
			response.Fail(ctx, gin.H{}, "满"+strconv.FormatFloat(shopInfo.SendMoney, 'f', 2, 64)+"元起能配送")
			return
		}
		addressId := ctx.PostForm("addressId")
		if len(addressId) == 0 {
			response.Fail(ctx, gin.H{}, "缺少地址标识")
			return
		}
		Db.Debug().Table("cat_meal_address").Where("id=? and uid =?", addressId, user.(model.UserInfo).Uid).First(&adInfo)
		if adInfo.Id == 0 {
			response.Fail(ctx, gin.H{}, "地址有误")
			return
		}
		//计算收货地址与店铺地址的距离
		newLat, _ := strconv.ParseFloat(adInfo.Latitude, 64) //64位转字符串
		newlng, _ := strconv.ParseFloat(adInfo.Longitude, 64)
		redisDB := common.GetRedis()
		_, err := redisDB.GeoAdd("shopList", &redis.GeoLocation{
			Name:      "address_id_" + strconv.Itoa(adInfo.Id),
			Longitude: newlng,
			Latitude:  newLat,
		}).Result()
		if err != nil {
			return
		}
		resDist, _ := redisDB.GeoDist("shopList", "address_id_"+strconv.Itoa(adInfo.Id), "shop_"+shopId, "m").Result()
		if resDist > shopInfo.SendDistance {
			response.Fail(ctx, gin.H{}, "超出配送范围，只支持"+strconv.FormatFloat(resDist, 'f', 2, 64)+"m")
			return
		}

		//通过距离计算配送费
		var logis map[string]int
		err = json.Unmarshal([]byte(shopInfo.AmountLogistics), &logis)
		if err != nil {
			return
		}
		for key, lValue := range logis {
			fmt.Printf("%T--%T--%T", key, lValue, resDist)
			area, _ := strconv.ParseFloat(key, 64)
			lValue2, _ := strconv.ParseFloat(strconv.Itoa(lValue), 64)
			if resDist > area {
				AmountLogistics = lValue2
			}
		}
	}
	//优惠券
	couponId := ctx.PostForm("couponId")
	var CouponMoney float64
	if len(couponId) != 0 {
		var MyCou model.MyCouponsInfo
		Db.Debug().Table("cat_meal_coupons").Where("status=0 and id=? and uid =? and shopId = ?", couponId, user.(model.UserInfo).Uid, shopId).First(&MyCou)
		if allPrice >= MyCou.MoneyHreshold {
			CouponMoney = MyCou.Money
		}
	}
	//会员等级
	var AmountLevel float64
	if user.(model.UserInfo).Level > 0 {
		var myLevel model.LevelInfo
		Db.Debug().Table("cat_meal_level").Where(" id=?", user.(model.UserInfo).Level).First(&myLevel)
		AmountLevel, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", myLevel.Rebate*allPrice/100), 64)
	}
	//下单
	ShopIdZt, _ := strconv.Atoi(shopId)
	CouponsId, _ := strconv.Atoi(couponId)
	var insert = model.InsertOrder{
		ShopIdZt:        ShopIdZt,
		ShopNameZt:      shopInfo.ShopName,
		Status:          0,
		OrderNumber:     util.OrderNumber(),
		Price:           allPrice,
		Amount:          allPrice,
		AmountReal:      allPrice + AmountLogistics - CouponMoney - AmountLevel,
		Uid:             user.(model.UserInfo).Uid,
		IsNeedLogistics: 0,
		GoodsNumber:     goodsNumber,
		PeisongType:     sendType,
		HxNumber:        strconv.Itoa(time.Now().Hour()) + strconv.Itoa(time.Now().Minute()) + strconv.Itoa(time.Now().Second()),
		QuDanHao:        strconv.Itoa(time.Now().Hour()) + strconv.Itoa(time.Now().Minute()) + strconv.Itoa(time.Now().Second()),
		Remark:          ctx.PostForm("remark"),
		ProvinceId:      adInfo.ProvinceId,
		CityId:          adInfo.CityId,
		DistrictId:      adInfo.DistrictId,
		Address:         adInfo.Address,
		Latitude:        adInfo.Latitude,
		Longitude:       adInfo.Longitude,
		LinkMan:         adInfo.LinkMan,
		Mobile:          adInfo.Mobile,
		CouponsId:       CouponsId,
		AmountCoupon:    CouponMoney,
		AmountLevel:     AmountLevel,
	}
	err := Db.Transaction(func(tx *gorm.DB) error {
		if err := Db.Debug().Table("cat_meal_order").Create(&insert).Error; err != nil {
			// 返回任何错误都会回滚事务
			tx.Rollback()
			return err
		}
		//修改优惠券状态
		if len(couponId) > 0 {
			if err := Db.Debug().Table("cat_meal_user_coupons").Where("uid =? and id=? ", user.(model.UserInfo).Uid, couponId).Update("status", "2").Error; err != nil {
				tx.Rollback()
				return err
			}
		}
		for _, v := range goodsOrder {
			goodsOrderInsert := model.OrderGoods{
				OrderId:   insert.Id,
				Pic:       v.Pic,
				Property:  v.Property,
				GoodsName: v.GoodsName,
				Number:    v.Number,
				Amount:    v.Amount,
			}
			if err := Db.Debug().Table("cat_meal_order_goods").Create(&goodsOrderInsert).Error; err != nil {
				tx.Rollback()
				return err
			}
		}
		return tx.Commit().Error
	})
	if err != nil {
		return
	}

	response.Success(ctx, gin.H{"info": insert}, "success")

}

// OrderList 订单列表多趣go体验版
func OrderList(ctx *gin.Context) {
	status := ctx.PostForm("status")
	if len(status) == 0 {
		status = "status != -1"
	} else {
		status = "status = " + status
	}

	page := ctx.PostForm("page")
	if len(page) == 0 {
		page = "0"
	}
	p, _ := strconv.Atoi(page)
	var site = 2
	offset := (p - 1) * site
	Db := common.GetDB()
	user, _ := ctx.Get("user")
	var orderInfoList, orderInfoList2 []model.InsertOrder
	Db.Debug().Table("cat_meal_order").Where("uid=?", user.(model.UserInfo).Uid).Where(status).Order("id desc").
		Limit(site).Offset(offset).Find(&orderInfoList)
	for _, v := range orderInfoList {
		var orderGoods []model.OrderGoods
		Db.Debug().Table("cat_meal_order_goods").Where("order_id=?", v.Id).Find(&orderGoods)
		v.OrderGoods = orderGoods
		orderInfoList2 = append(orderInfoList2, v)
	}
	var count int64
	Db.Debug().Table("cat_meal_order").Where("uid=? and shopIdZt=?", user.(model.UserInfo).Uid).Where(status).Count(&count)
	response.Success(ctx, gin.H{"list": orderInfoList2, "page_site": site, "page_no": p + 1, "count": count}, "success")
}

// CancelOrder 取消订单
func CancelOrder(ctx *gin.Context) {
	Id := ctx.PostForm("orderId")
	if len(Id) == 0 {
		response.Fail(ctx, gin.H{}, "缺少订单标识")
		return
	}
	Db := common.GetDB()
	user, _ := ctx.Get("user")
	var orderInfo model.InsertOrder
	Db.Debug().Table("cat_meal_order").Where("uid=? and id=?", user.(model.UserInfo).Uid, Id).First(&orderInfo)
	if orderInfo.Id == 0 {
		response.Fail(ctx, gin.H{}, "订单错误")
		return
	}
	if orderInfo.Status != 0 {
		response.Fail(ctx, gin.H{}, "订单状态错误")
		return
	}
	Db.Debug().Table("cat_meal_order").
		Where("uid=? and id=?", user.(model.UserInfo).Uid, Id).Update("status", "4")
	response.Success(ctx, gin.H{}, "success")
}

// ConfirmOrder 确认收货订单
func ConfirmOrder(ctx *gin.Context) {
	Id := ctx.PostForm("orderId")
	if len(Id) == 0 {
		response.Fail(ctx, gin.H{}, "缺少订单标识")
		return
	}
	Db := common.GetDB()
	user, _ := ctx.Get("user")
	var orderInfo model.InsertOrder
	Db.Debug().Table("cat_meal_order").Where("uid=? and id=?", user.(model.UserInfo).Uid, Id).First(&orderInfo)
	if orderInfo.Id == 0 {
		response.Fail(ctx, gin.H{}, "订单错误")
		return
	}
	if orderInfo.Status == 1 || orderInfo.Status == 2 {
		err := Db.Transaction(func(tx *gorm.DB) error {
			if err := Db.Debug().Table("cat_meal_order").Where("uid=? and id=?", user.(model.UserInfo).Uid, Id).Update("status", "3").Error; err != nil {
				// 返回任何错误都会回滚事务
				tx.Rollback()
				return err
			}
			err := model.ChangeScore(Db, user.(model.UserInfo), int(orderInfo.Price), 0)
			if err != nil {
				return err
			}
			return nil
		})
		if err != nil {
			util.LogError("确认收货" + err.Error())
			response.Fail(ctx, gin.H{}, err.Error())
			return
		}
		response.Success(ctx, gin.H{}, "success")
		return
	}
	response.Fail(ctx, gin.H{}, "订单状态错误")

}

// RemoveOrder 删除订单
func RemoveOrder(ctx *gin.Context) {
	Id := ctx.PostForm("orderId")
	if len(Id) == 0 {
		response.Fail(ctx, gin.H{}, "缺少订单标识")
		return
	}
	Db := common.GetDB()
	user, _ := ctx.Get("user")
	var orderInfo model.InsertOrder
	Db.Debug().Table("cat_meal_order").Where("uid=? and id=?", user.(model.UserInfo).Uid, Id).First(&orderInfo)
	if orderInfo.Id == 0 {
		response.Fail(ctx, gin.H{}, "订单错误")
		return
	}
	if orderInfo.Status == 4 || orderInfo.Status == 3 {
		Db.Debug().Table("cat_meal_order").Where("uid=? and id=?", user.(model.UserInfo).Uid, Id).Update("status", "-1", "dateClose", util.DateFormat(0))
		response.Success(ctx, gin.H{}, "success")
		return
	}
	response.Fail(ctx, gin.H{}, "订单状态错误")

}
